package com.my.springboot.tuling.concurrent;

import java.util.concurrent.*;

/**
 * corePoolSize核心线程数
 * BlockingQueue阻塞队列 FIFO先进先出
 * maximumPoolSize最大线程数
 * keepAliveTime活动时间
 */
public class ThreadPoolDemo {
    public static void main(String[] args) {
        // 阿里不推荐使用一下三种
        // CPU100%  OOM    woker》程序员》线程》CPU100%
        // newCachedThreadPool：maximumPoolSize 指定为MAX，并发高会导致cpu100%，oom
        ExecutorService executorService1 = Executors.newCachedThreadPool();//快
        // 阿里不推荐使用，原因newFixedThreadPool使用LinkedBlockingQueue无界阻塞队列，本身支持参数配置大小，但newFixedThreadPool配置的为无限大，未提供参数修改
        //this(Integer.MAX_VALUE);
        ExecutorService executorService2 = Executors.newFixedThreadPool(10);//慢
        ExecutorService executorService3 = Executors.newSingleThreadExecutor();//最慢


        // 决绝策略
       RejectedExecutionHandler rejectedExecutionHandler = new RejectedExecutionHandler() {
            @Override
            public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                // 存数据库
                // todo
                System.out.println("执行拒绝策略，存储数据库");
            }
        };

        // 推荐使用自定义线程
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10,20,0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingDeque<>(10),rejectedExecutionHandler);
        // 结果1-10，21-30，11-20，为什么不是1-10-20-30
        // 自定义线程池，第31个开始报错，原因：线程先放核心线程数为1-10，核心线程满了，放入阻塞队列11-20，
        // 大于核心数且队列已满21-30放入非核心线程数（20-10），大于30的则执行拒绝策略。Task只会再核心线程和非核心线程，则从队列取
        // 节省资源

        // execute和submit区别
        // 1、submit有返回值，execute无返回值2、
        for (int i = 0; i < 100; i++){
            threadPoolExecutor.execute(new MyTask(i));
        }
    }
}

class MyTask implements Runnable{
    private  int i;

    public MyTask(int i) {
        this.i = i;
    }

    public int getI() {
        return i;
    }

    public void setI(int i) {
        this.i = i;
    }

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() +"程序员做第" + i + "个项目");
        try{
            Thread.sleep(3000L);//业务逻辑
        }catch (Exception e) {
            e.printStackTrace();
        }

    }
}
